/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
 *
 */

import path from 'path';

import { cloneDeep } from '@baize/wdk';
import { coreParameter, FileSet, hvigorCore, Input, Json5Reader, parseJsonFile, TaskInputValue } from '@ohos/hvigor';
import { findNodeEntryFiles, PkgContextInfoOpt } from '@ohos/hvigor-arkts-compose';
import * as fse from 'fs-extra';

import { buildOptionPath } from '../common/build-option-path-info.js';
import { projectOhosConfigManager } from '../common/global/project-ohos-config-manager.js';
import { BuildArtifactConst, BuildDirConst } from '../const/build-directory-const.js';
import { AbilityConst, CommonConst, CommonNodeConst, DefaultTargetConst, HvigorConfigConst, ValidateRegExp } from '../const/common-const.js';
import { InjectConst } from '../const/inject-const.js';
import { ApiVersion } from '../const/sdk-const.js';
import { AotCompileModeEnum } from '../enum/aot-compile-mode-enum.js';
import { CodeType } from '../enum/code-type-enum.js';
import { ModuleType } from '../enum/module-type-enum.js';
import { CoreModuleModelImpl } from '../model/module/core-module-model-impl.js';
import { TargetSourceSetModel } from '../model/source-set/source-set-model.js';
import { TargetSourceSetImpl } from '../model/source-set/target-source-set-impl.js';
import { AppOpt } from '../options/build/app-ohos-config.js';
import { RuntimeOnlyObj } from '../options/build/build-opt.js';
import { AppJson } from '../options/configure/app-json-options.js';
import { ConfigJson } from '../options/configure/config-json-options.js';
import { ModuleJson } from '../options/configure/module-json-options.js';
import { RouterMapOptions } from '../options/configure/router-map-options.js';
import { StartupOptions } from '../options/configure/startup-options.js';
import { buildOptionManager } from '../project/build-option/build-mode-manager.js';
import { Dependency, DependencyType } from '../project/dependency/core/dependency-interface.js';
import { DependencyManager } from '../project/dependency/dependency-manager.js';
import { getUnionSet } from '../utils/array-util.js';
import { getRuntimeOnlyObjMap } from '../utils/build-profile-utils.js';
import { collectByteCodeInfoAndOtherCompileEntrances, shouldTreatHarAsHap, IByteCodeHarInfo } from '../utils/byte-code-har-utils.js';
import { FileUtil } from '../utils/file-util.js';
import { Dep2RuntimeOnlyObj, HarTargetUtil } from '../utils/har-target-util.js';
import { HspTargetUtils } from '../utils/hsp-target-utils.js';
import { InjectUtil } from '../utils/inject-util.js';
import { getJson5Obj } from '../utils/json-util.js';
import { ohPackageLoader } from '../utils/loader/file/oh-package-loader.js';
import { OhosLogger } from '../utils/log/ohos-logger.js';
import { generateOhmUrl, removeSuffix } from '../utils/ohmurl-utils.js';
import { getStrategy, TStrategy } from '../utils/strategy.js';
import { shouldCompileArkTsWidget } from '../utils/task-util.js';
import { SdkVersionEnum } from '../version/sdk-version-enum.js';
import { SdkVersion } from '../version/sdk-version.js';
import { AbstractGenerateLoaderJson } from './abstract-generate-loader-json.js';
import { TaskNames } from './common/task-names.js';
import { PreBuild } from './pre-build.js';
import { TargetTaskService } from './service/target-task-service.js';
import { OhPackageJsonOpt } from './task/ohos-har-task.js';

import AppOptObj = AppJson.AppOptObj;
import ModuleOptObj = ModuleJson.ModuleOptObj;
import intermediatesRouterMapObj = RouterMapOptions.intermediatesRouterMapObj;
import AbilityObj = ModuleJson.AbilityObj;

const log: OhosLogger = OhosLogger.getLogger('GenerateLoaderJson');

const enum AotRolesEnum {
  WITH_AP_PATH = 'withApPath',
  WITHOUT_AP_PATH = 'withoutApPath',
  WITH_EMPTY = 'withEmpty',
  ERROR_INVALID_SUFFIX = 'invalidSuffix',
  ERROR_INVALID_PATH = 'invalidPath',
  ERROR_PARTIAL_EMPTY_PATH = 'partialEmptyPath',
  ERROR_MISMATCH_AOT_COMPILE_MODE = 'mismatchAotCompileMode',
}

type AotConfigsParams = {
  apiVersion: number;
  anBuildMode: string;
  apPath?: string;
  fallbackAnBuild: boolean;
};

/**
 * 生成loader需要的json文件
 *
 * @since 2022/3/3
 */
export class GenerateLoaderJson extends AbstractGenerateLoaderJson {
  private readonly aceLoaderJson: string;
  private readonly aceWidgetLoaderJson: string;
  private readonly nodeModulesPath: string;
  private hspNameOhmMap: object = {};
  private harNameOhmMap: object = {};
  private readonly hspResourcesMap: object;
  private readonly moduleSrcMainPath: string;
  private readonly moduleSrcMockPath: string;
  private readonly insightIntentJsonPath: string;
  private readonly mockConfigJsonPath: string;
  private readonly compileEntry: string[];
  private readonly otherCompileFiles: string[] = [];
  private readonly dynamicImportLibInfo: Record<string, DynamicImportObj>;
  private readonly moduleJson5Path: string;
  private readonly modulePath: string;
  private insightIntentJson: any;
  private readonly intermediatesRouterMapObjs: intermediatesRouterMapObj[];
  protected isPreview: boolean | undefined;
  private readonly etsSourcePath: string;
  private readonly needSubmitArkTsWidget: boolean;

  // 声明与aot相关的变量
  private readonly apPath?: string;
  private readonly tempApPath: string;
  private readonly tempApDir: string;
  private readonly anBuildOutPutPath: string;
  private readonly fallbackAnBuild: boolean;
  private readonly updateVersionInfo: Record<string, Record<string, string>> = {};

  private readonly declarationEntry: string[] = [];
  private pkgContextInfos: Record<string, PkgContextInfoOpt> = {};
  private readonly byteCodeHarInfo: Record<string, Omit<IByteCodeHarInfo, 'packageName'>> = {};

  private get useNormalizedOHMUrl() {
    return !!this.targetService.getBuildOption()?.strictMode?.useNormalizedOHMUrl;
  }

  @Input() private get isByteCodeHarOptimize() {
    return InjectUtil.isByteCodeHarOptimize();
  }

  declareInputs(): Map<string, TaskInputValue> {
    const map = super.declareInputs();
    const modulePkgJsonPath = this.isOhpmProject ? this.moduleModel.getOhPackageJson5Path() : this.moduleModel.getPackageJsonPath();
    const modulePkgJsonObj = getJson5Obj(modulePkgJsonPath);
    map.set('module_dependencies', JSON.stringify(modulePkgJsonObj.dependencies));

    const projectPkgJsonPath = this.isOhpmProject ? this.projectModel.getOhPackageJson5Path() : this.projectModel.getPackageJsonPath();
    const projectOhPkgJsonObj = getJson5Obj(projectPkgJsonPath);
    map.set('overrides', projectOhPkgJsonObj.overrides);
    map.set('project_dependencies', JSON.stringify(projectOhPkgJsonObj.dependencies));
    map.set(CommonConst.USE_NORMALIZED_OHM_URL, this.useNormalizedOHMUrl);
    map.set('isOhosTest', InjectUtil.isOhosTest());
    this.service.getHarDependencies().forEach((dependency) => {
      if (dependency.isByteCodeHarDependency()) {
        return;
      }
      const dependencyModuleJsonObj = dependency.getModuleJsonObj();
      map.set('dependencyModuleAbility', JSON.stringify(dependencyModuleJsonObj?.module?.abilities));
    });

    // 是否开启全编
    map.set('isFullCompilationEnabled', this.isFullCompilationEnabled());

    // 判断buildConfig.json中的patchConfig是否有变化
    const buildConfigPath = this.pathInfo.getBuildConfigPath();
    if (fse.existsSync(buildConfigPath)) {
      const loaderConfig = getJson5Obj(buildConfigPath);
      map.set('patchConfig', JSON.stringify(loaderConfig.patchConfig));
    }
    map.set('appStartupFileName', this.appStartupFileName ?? '');
    this.declareDynamicImportInputs(map);
    return map
      .set('compileMode', this.targetCompileMode.toString())
      .set('nodeModulesPath', this.nodeModulesPath)
      .set('targetConfig', JSON.stringify(this.targetData.getTargetOpt()))
      .set('hspNameOhmMap', JSON.stringify(this.hspNameOhmMap))
      .set('harNameOhmMap', JSON.stringify(this.harNameOhmMap))
      .set('anBuildMode', this.targetService.getAnBuildMode() ?? '')
      .set('apPath', this.apPath ?? '')
      .set('fallbackAnBuild', this.fallbackAnBuild)
      .set('isHarWithCoverage', this.isHarWithCoverage())
      .set('compileApiVersion', this.compileApiVersion)
      .set('compatibleApiVersion', this.compatibleApiVersion)
      .set('isByteCodeHar', this.targetService.isByteCodeHar())
      .set('shouldTreatHarAsHap', this.shouldTreatHarAsHap())
      .set('isBundledDependencies', this.isBundledDependencies)
      .set('needSubmitArkTsWidget', this.needSubmitArkTsWidget);
  }

  declareDynamicImportInputs(map: Map<string, TaskInputValue>) {
    const moduleDependenciesList = Object.keys(this.getDependencies(this.moduleModel, false));
    const projectDependenciesList = Object.keys(this.getDependencies(this.projectModel, false));
    const runtimeOnlyObjMap = getRuntimeOnlyObjMap(
      this.module.getNodeDir(),
      this.targetService.getBuildOption()?.arkOptions?.runtimeOnly,
      getUnionSet(projectDependenciesList, moduleDependenciesList),
    );

    for (const [key, value] of runtimeOnlyObjMap) {
      map.set(key, value);
    }

    this.service.getHarModuleDependencies().forEach(([moduleName, dependency]) => {
      const dependencies = dependency.getPackageJsonObj()?.dependencies || {};
      const inputs = getRuntimeOnlyObjMap(
        dependency.getDependencyRootPath(),
        this.getLocalDependencyRuntimeOnly(dependency),
        getUnionSet(projectDependenciesList, Object.keys(dependencies)),
        moduleName,
      );
      for (const [key, value] of inputs) {
        map.set(key, value);
      }
    });
  }

  declareInputFiles(): FileSet {
    const fileSet = new FileSet();

    // 判断ap文件是否修改
    if (this.apPath && fse.existsSync(this.apPath)) {
      fileSet.addEntry(this.apPath, { isDirectory: false });
    }

    // 判断InsightIntent.json是否修改
    if (this.insightIntentJsonPath && fse.existsSync(this.insightIntentJsonPath)) {
      fileSet.addEntry(this.insightIntentJsonPath);
    }

    // 判断mock-config.json5是否修改
    if (this.mockConfigJsonPath && fse.existsSync(this.mockConfigJsonPath)) {
      fileSet.addEntry(this.mockConfigJsonPath);
    }

    this.addStartupInputFiles(fileSet);

    if (fse.existsSync(this.pathInfo.getIntermediatesPkgContextInfoPath())) {
      fileSet.addEntry(this.pathInfo.getIntermediatesPkgContextInfoPath());
    }

    const entryFile = this.getModuleEntryFile();
    if (this.isHarWithCoverage() && fse.existsSync(entryFile)) {
      fileSet.addEntry(entryFile);
    }

    const intermediatesToLoaderRouterMap = this.pathInfo.getIntermediatesRouterMap(BuildArtifactConst.LOADER_ROUTER_MAP_FILE_NAME);
    if (fse.existsSync(intermediatesToLoaderRouterMap)) {
      const intermediatesTempRouterMapOpt: RouterMapOptions.RouterMapOpt = getJson5Obj(intermediatesToLoaderRouterMap);
      if (intermediatesTempRouterMapOpt.routerMap?.length) {
        fileSet.addEntry(intermediatesToLoaderRouterMap);
      }
    }

    const intermediatesTempRouterMapFilePath = this.pathInfo.getIntermediatesRouterMap(
      this.targetService.getRouterMapJsonFileName(this.moduleModel) ?? BuildArtifactConst.TEMP_ROUTER_MAP_FILE_NAME,
    );
    if (fse.existsSync(intermediatesTempRouterMapFilePath)) {
      fileSet.addEntry(intermediatesTempRouterMapFilePath);
    }

    if (this.allowToCollectEtsFolder() && fse.existsSync(this.etsSourcePath)) {
      fileSet.addEntry(this.etsSourcePath, { isDirectory: true });
    }

    this.declareByteCodeHarInputFiles(fileSet);
    this.declareDynamicImportInputFiles(fileSet);
    return fileSet;
  }

  private addStartupInputFiles(fileSet: FileSet) {
    if (this.appStartupPath && fse.existsSync(this.appStartupPath)) {
      fileSet.addEntry(this.appStartupPath);
    }

    if (this.intermediateTempStartupFilePath && fse.existsSync(this.intermediateTempStartupFilePath)) {
      fileSet.addEntry(this.intermediateTempStartupFilePath);
    }
  }

  private isFullCompilationEnabled() {
    return !coreParameter.properties[HvigorConfigConst.OHOS_COMPILE_LIB_ENTRY];
  }

  private getEtsSourcePath(pkgRoot: string) {
    return path.join(pkgRoot, BuildDirConst.SRC, BuildDirConst.MAIN, CodeType.ETS);
  }

  get isBundledDependencies(): boolean {
    return this.targetService.isBundledDependencies();
  }

  /**
   * 增加动态import har包的src/main/ets依赖
   * @param fileSet
   * @private
   */
  private declareDynamicImportInputFiles(fileSet: FileSet) {
    if (!this.allowToCollectDependencyEtsFolder()) {
      return;
    }
    const dynamicImportList: string[] = [];
    const key2Dependency: Map<string, Dependency> = new Map();
    this.service.getHarDependencies().forEach((dependency) => {
      key2Dependency.set(dependency.getDependencyName(), dependency);
      const depDynamicImportList = dependency.isLocal()
        ? this.getLocalDependencyDynamicImportList(dependency)
        : this.getRemoteDependencyDynamicImportList(dependency);
      dynamicImportList.push(...depDynamicImportList);
    });
    const packages = this.targetService.getBuildOption()?.arkOptions?.runtimeOnly?.packages;
    dynamicImportList.concat(packages || []).forEach((dependencyKey) => {
      const dependency = key2Dependency.get(dependencyKey);
      if (!dependency) {
        return;
      }
      const etsSourcePath = this.getEtsSourcePath(dependency.getDependencyRootPath());
      if (fse.existsSync(etsSourcePath)) {
        fileSet.addEntry(etsSourcePath, { isDirectory: true });
      }
    });
  }

  private declareByteCodeHarInputFiles(fileSet: FileSet) {
    const generatedModuleInfoPath = this.pathInfo.getGenerateModuleInfoPath();
    if (this.targetService.isByteCodeHar() && fse.existsSync(generatedModuleInfoPath)) {
      fileSet.addEntry(generatedModuleInfoPath, { isDirectory: false });
    }

    Object.keys(this.byteCodeHarInfo).forEach((key) => {
      const { abcPath, sourceMapsPath } = this.byteCodeHarInfo[key];
      fileSet.addEntry(abcPath, { isDirectory: false });
      if (sourceMapsPath) {
        fileSet.addEntry(abcPath, { isDirectory: false });
      }
    });

    this.otherCompileFiles.forEach((filePath) => {
      fileSet.addEntry(filePath, { isDirectory: false });
    });
  }

  declareOutputFiles(): FileSet {
    const fileSet = new FileSet().addEntry(this.aceLoaderJson, { isDirectory: false });
    if (this.needSubmitArkTsWidget) {
      fileSet.addEntry(this.aceWidgetLoaderJson, { isDirectory: false });
    }
    return fileSet;
  }

  initTaskDepends() {
    this.declareDepends(PreBuild.name);
  }

  constructor(taskService: TargetTaskService) {
    super(taskService, TaskNames.Task.GENERATE_LOADER_JSON);
    this.aceLoaderJson = this.pathInfo.getLoaderJsonPath();
    this.aceWidgetLoaderJson = this.pathInfo.getWidgetLoaderJsonPath();
    this.nodeModulesPath = path.resolve(taskService.getTargetData().getPathInfo().getInterMediatesLoaderOutPath(), CommonNodeConst.NODE_MODULES);
    this.hspResourcesMap = this.getHspResourcesMap();
    this.moduleSrcMainPath = taskService.getTargetData().getPathInfo().getModuleSrcMainPath();
    this.modulePath = taskService.getTargetData().getPathInfo().getModulePath();

    this.moduleSrcMockPath = taskService.getTargetData().getPathInfo().getModuleSrcMockPath();
    this.mockConfigJsonPath = path.resolve(this.moduleSrcMockPath, BuildArtifactConst.MOCK_CONFIG_JSON5);
    this.moduleJson5Path = path.resolve(this.moduleSrcMainPath, BuildArtifactConst.MODULE_JSON5);
    this.etsSourcePath = path.join(this.pathInfo.getModuleSrcMainPath(), CodeType.ETS);

    // InsightIntent.json文件路径
    this.insightIntentJsonPath = path.resolve(this.pathInfo.getModuleSrcMainResourceBaseProfilePath(), BuildArtifactConst.INSIGHT_INTENT_JSON);

    // InsightIntent.json中所有意图api的srcEntry存入compileEntry
    this.compileEntry = this.readInsightIntentSrcEntry();

    this.dynamicImportLibInfo = {};

    this.intermediatesRouterMapObjs = [];

    // 定义aot相关变量
    this.tempApDir = this.pathInfo.getIntermediatesApPath();
    this.tempApPath = path.resolve(this.tempApDir, `${this.moduleName}.ap`);
    this.anBuildOutPutPath = path.resolve(this.pathInfo.getInterMediatesLoaderOutPath(), AotCompileModeEnum.AN, AotCompileModeEnum.ARM64_V8A);
    this.isPreview = hvigorCore.getExtraConfig().get(InjectConst.BUILD_ROOT) === BuildDirConst.PREVIEW_BUILD_PATH;
    this.fallbackAnBuild = InjectUtil.isTestFrameWork() ? false : this.moduleModel.isHarModule();
    const apPath = this.targetService.getApPath();
    if (apPath) {
      this.apPath = path.resolve(this.moduleModel.getProjectDir(), apPath);
    }

    const targetSourceSetModel: TargetSourceSetModel = taskService.getTargetData().getModuleSourceSetModel() as TargetSourceSetModel;
    const targetRes = targetSourceSetModel.getModuleTargetRes();
    this.needSubmitArkTsWidget = shouldCompileArkTsWidget(TargetTaskService.getFormJsonArr(targetRes));
  }

  async beforeAlwaysAction(): Promise<void> {
    await super.beforeAlwaysAction();

    this.setPkgContextInfos();
    this.hspNameOhmMap = this.getHspNameOhmMap();
    this.harNameOhmMap = this.getHarNameOhmMap();
    this.setByteCodeHarInfoAndOtherCompileFiles();
  }

  private isHapOrHsp() {
    return this.moduleModel.isHspModule() || this.moduleModel.isHapModule() || this.shouldTreatHarAsHap();
  }

  private setByteCodeHarInfoAndOtherCompileFiles() {
    if (!this.useNormalizedOHMUrl || !this.isHapOrHsp()) {
      return;
    }
    const { byteCodeInfo, otherCompileEntrances } = collectByteCodeInfoAndOtherCompileEntrances(this.targetService);
    byteCodeInfo.forEach((info) => {
      const packageName = info.packageName;
      this.byteCodeHarInfo[packageName] = {
        abcPath: info.abcPath,
        compatibleSdkVersion: info.compatibleSdkVersion,
        compatibleSdkVersionStage: info.compatibleSdkVersionStage,
        ...(info.sourceMapsPath ? { sourceMapsPath: info.sourceMapsPath } : {}),
        ...(info.insightIntentJsonPath ? { insightIntent: info.insightIntentJsonPath } : {}),
      };
    });
    otherCompileEntrances.forEach((isFolder, filePah) => {
      if (isFolder) {
        this.collectCompileFiles(filePah, this.otherCompileFiles);
      } else {
        this.otherCompileFiles.push(filePah);
      }
    });
  }

  protected beforeTask() {
    super.beforeTask();
    if (fse.existsSync(this.aceWidgetLoaderJson)) {
      fse.removeSync(this.aceWidgetLoaderJson);
    }
  }

  protected getWorkerConfig(): string[] | undefined {
    // har只返回自己的worker配置
    if (this.moduleModel.isHarModule()) {
      return this.targetService.getWorkerConfig().length === 0 ? undefined : this.targetService.getWorkerConfig();
    }

    // 当前模块和本地模块，从build-profile.json5里取
    const workerConfigs = this.service.getHarModuleDependencies().reduce((workers: string[], moduleDependency: [string, Dependency]) => {
      const harModule = <CoreModuleModelImpl>this.projectModel.getModuleModelByName(moduleDependency[0]);
      if (harModule === undefined) {
        return workers;
      }
      const targetName = HarTargetUtil.calDepHarTargets(this.targetService).get(moduleDependency[0]) ?? 'default';
      const harModuleBuildOption = buildOptionManager.getTargetBuildOption(moduleDependency[0], targetName);

      const harWorkerConfig = FileUtil.convertToAbsolutePaths(harModuleBuildOption.sourceOption?.workers ?? [], harModule.getProjectDir());
      return harWorkerConfig ? workers.concat(harWorkerConfig) : workers;
    }, this.targetService.getWorkerConfig() ?? []);

    const harModulePaths = this.service.getHarModuleDependencyPaths();

    // 三方包har，从oh-package.json5的metadata字段取
    this.service.getHarDependencies().forEach((harDep) => {
      if (harModulePaths.includes(harDep.getDependencyRootPath())) {
        return;
      }
      const packageObj: OhPackageJsonOpt = getJson5Obj(harDep.getPackageFilePath(), 'utf-8');
      if (packageObj?.metadata?.workers) {
        workerConfigs.push(...FileUtil.convertToAbsolutePaths(packageObj.metadata.workers, harDep.getDependencyRootPath()));
      }
    });

    // 因为历史原因，当没有worker时返回undefined
    return workerConfigs.length === 0 ? undefined : workerConfigs;
  }

  /**
   * 收集sourcePath目录下的.js/.ets./.ts文件到compileEntry中
   * @private
   */
  private collectCompileFiles(sourcePath: string, files = this.compileEntry) {
    if (!fse.existsSync(sourcePath)) {
      return;
    }
    const supportExtensions = ['.ets', '.ts', '.js'];
    const queue = [sourcePath];
    while (queue.length) {
      const basePath = queue.shift()!;
      fse.readdirSync(basePath).forEach((filename) => {
        const filePath = path.join(basePath, filename);
        const stat = fse.statSync(filePath);
        if (stat.isDirectory()) {
          queue.push(filePath);
          return;
        }
        if (stat.isFile() && supportExtensions.includes(path.extname(filePath).toLowerCase())) {
          files.push(filePath);
        }
      });
    }
  }

  private allowToCollectEtsFolder() {
    if (this.targetName === DefaultTargetConst.OHOS_TEST_TARGET || !this.isFullCompilationEnabled()) {
      return false;
    }

    return this.moduleModel.isHspModule() || this.moduleModel.isHarModule();
  }

  private allowToCollectDependencyEtsFolder() {
    if (!this.isFullCompilationEnabled()) {
      return false;
    }
    return this.moduleModel.isHspModule() || this.moduleModel.isHapModule();
  }

  private collectDepEtsFolderFilesEntry(dependency: Dependency) {
    if (this.allowToCollectDependencyEtsFolder()) {
      this.collectCompileFiles(this.getEtsSourcePath(dependency.getDependencyRootPath()));
    }
  }

  private checkByteCodeHar() {
    if (this.useNormalizedOHMUrl || !this.isHapOrHsp()) {
      return;
    }
    const pkgNames = this.service
      .getHarDependencies()
      .filter((dependency) => dependency.isByteCodeHarDependency())
      .map((dependency) => dependency.getPackageName());
    if (!pkgNames.length) {
      return;
    }
    this._log.printErrorExit('BYTECODE_HARS_%S_NOT_SUPPORTED_WHEN_USENORMALIZEDOHMURL_IS_NOT_TRUE', [pkgNames.join(', ')]);
  }

  /**
   * 是否har模块，且是否在跑localTest或ohosTest或preview
   * @private
   */
  private shouldTreatHarAsHap(): boolean {
    return this.moduleModel.isHarModule() && shouldTreatHarAsHap(this.targetName);
  }

  private isHarWithCoverage() {
    return this.moduleModel.isHarModule() && InjectUtil.isOhosTestCoverage();
  }

  private getModuleEntryFile() {
    const main = this.packageJsonObj.main ? this.packageJsonObj.main : BuildArtifactConst.INDEX_ETS;
    return path.resolve(this.pathInfo.getModulePath(), main);
  }

  /**
   * har模块在进行覆盖率报告的unitTest时，需要把入口文件编译进去，不然初始化的模块无法输出覆盖率报告
   * @private
   */
  private processHarUnitTestWithCoverage() {
    const filePath = this.getModuleEntryFile();
    if (this.isHarWithCoverage() && fse.existsSync(filePath)) {
      this.compileEntry.push(filePath);
    }
  }

  private processCodeFiles(files: string[]) {
    const declareFileReg = /\.d\.(e)?ts$/i;
    return Array.from(new Set(files))
      .filter((file) => !declareFileReg.test(file) && fse.existsSync(file))
      .map((file) => fse.realpathSync.native(file));
  }

  private setPkgContextInfos(): void {
    if (fse.existsSync(this.pathInfo.getIntermediatesPkgContextInfoPath())) {
      this.pkgContextInfos = getJson5Obj(this.pathInfo.getIntermediatesPkgContextInfoPath());
    }
  }

  protected doTaskAction(): void {
    this.checkByteCodeHar();

    const targetSourceSet = this.moduleModel.getSourceSetByTargetName(this.targetName) as TargetSourceSetImpl;
    if (this.targetName === DefaultTargetConst.OHOS_TEST_TARGET) {
      const name = targetSourceSet.getModuleTargetRes()?.getModuleJsonOpt()?.module?.name;
      if (name) {
        // 将xxx_test 的moduleName前置，使os侧寻址正确
        this.modulePathMap = {
          [name]: this.module.getNodeDir(),
          ...this.modulePathMap,
        };
      }
    }

    this.processHarUnitTestWithCoverage();

    // 添加mock-config.json5下的路径到compileEntry
    // 仅在预览器和ohosTest、localTest下支持mock
    const isOhosTest = this.targetName === CommonConst.OHOS_TEST;
    const isLocalTest = InjectUtil.isLocalTest();
    if (this.isPreview || isOhosTest || isLocalTest) {
      this.collectMockFileEntry(this.modulePath, this.mockConfigJsonPath);
    }

    if (this.allowToCollectEtsFolder()) {
      this.collectCompileFiles(this.etsSourcePath);
    }

    // insight_intent.json的业务校验
    if (fse.existsSync(this.insightIntentJsonPath)) {
      this.validateForInsightIntentJson();
    }

    this.processDeclarationEntry();

    // 处理动态import
    this.processDynamicImport();

    // 处理byteCodeHar
    this.processByteCodeHar();

    // 处理appStartup
    this.processAppStartupConfig(this.appStartupPath);

    // 将模块routerMap配置信息传递给compileEntry和dynamicImportLibInfo
    this.processRouterMap();

    // 将字节码har依赖的本地或远程源码har的worker/runtimeOnly/routerMap相关信息写入compileEntry
    this.processBundledDependencies();

    // 处理hap/hsp的版本号更新表
    this.processUpdateVersionInfo();

    // 处理hap/hsp依赖har的ability-srcEntry
    this.collectDepAbilitySrcEntryArr();

    // 处理hap/hsp依赖har的insightIntent-srcEntry
    this.addHarDepInsightSrcEntry();

    // 处理aot相关的字段
    const aotFields = this.handleAotFields();
    const loaderJson: Record<string, unknown> = {
      workers: this.workerConfig,
      modulePathMap: this.modulePathMap,
      compileMode: this.targetCompileMode,
      projectRootPath: this.projectRootPath,
      nodeModulesPath: this.nodeModulesPath,
      byteCodeHarInfo: this.byteCodeHarInfo,
      declarationEntry: this.declarationEntry,
      moduleName: targetSourceSet.getModuleTargetRes()?.getModuleJsonOpt()?.module?.name,
      hspNameOhmMap: this.hspNameOhmMap,
      harNameOhmMap: this.harNameOhmMap,
      packageManagerType: this.isOhpmProject ? 'ohpm' : 'npm',
      compileEntry: this.processCodeFiles(this.compileEntry),
      otherCompileFiles: this.processCodeFiles(this.otherCompileFiles),
      dynamicImportLibInfo: this.dynamicImportLibInfo,
      routerMap: this.intermediatesRouterMapObjs,
      hspResourcesMap: this.hspResourcesMap,
      updateVersionInfo: this.updateVersionInfo,
      ...aotFields,
    };

    if (this.targetService.isByteCodeHar()) {
      loaderJson.byteCodeHar = true;
    }

    const buildConfigPath = this.pathInfo.getBuildConfigPath();
    if (this.isPreview || InjectUtil.isLocalTest()) {
      loaderJson.buildConfigPath = path.relative(this.modulePath, buildConfigPath);
    }

    // 添加冷重载需要的参数
    if (fse.existsSync(buildConfigPath) && !InjectUtil.isOhosTest()) {
      const loaderConfig = getJson5Obj(buildConfigPath);
      loaderJson.patchConfig = loaderConfig.patchConfig;
    }
    fse.outputJSONSync(this.aceLoaderJson, loaderJson, { spaces: 2 });
    // 卡片的loader.json区分一下，目前没区别，后续可能要做区分
    if (this.needSubmitArkTsWidget) {
      fse.outputJSONSync(this.aceWidgetLoaderJson, loaderJson, { spaces: 2 });
    }
  }

  private processByteCodeHar() {
    // 字节码har本身需要写入
    const generatedModuleInfoPath = this.pathInfo.getGenerateModuleInfoPath();
    if (this.targetService.isByteCodeHar() && fse.existsSync(generatedModuleInfoPath)) {
      this.compileEntry.push(generatedModuleInfoPath);
    }
  }

  /**
   * 在编hap/hsp时，如果依赖链中存在字节码HAR（为避免阅读困难，针对该字节码HAR，使用A替代）：
   * 1.需要收集A自身的declarationEntry：储存了自身的worker和runtimeOnly.sources对应的ohmurl
   * 2.需要检测A中的runtimeOnly.packages，如果存在【字节码HAR】依赖，则【字节码HAR】入口的ohmurl，也需要收集；
   *   针对这一步，理论上可以在编译A的时候，进行收集处理。但，如果依赖的版本号不是固定的，则存在编译时的版本号和集成时的版本号不一致，从而导致ohmurl错误。
   *
   * 存在以上处理逻辑的原因，是因为在生成abc的时候，存在针对未使用的代码裁减的逻辑，达到减少abc体积的目的。
   * 然而，worker和变量动态import，属于运行时的范畴，在编译期间无法得知，如果把这部分逻辑裁减掉，就会导致运行时报错。
   * @param dependency
   * @param pkgName2DepMap
   * @private
   */
  private collectByteCodeHarDeclarationEntry(dependency: Dependency, pkgName2DepMap: Map<string, Dependency>): void {
    const packageJson = dependency.getPackageJsonObj() as OhPackageJsonOpt;
    if (dependency.isByteCodeHarDependency()) {
      // 收集字节码HAR的workers, 动态import的ohmurl
      const declarationEntry = packageJson.metadata?.declarationEntry || [];
      this.declarationEntry.push(...declarationEntry);
    }
    const packages = packageJson.metadata?.runtimeOnly?.packages;
    this.collectRuntimeDynamicImportByteCodeHarDeclarationEntry(pkgName2DepMap, packages);
  }

  private collectRuntimeDynamicImportByteCodeHarDeclarationEntry(pkgName2DepMap: Map<string, Dependency>, packages?: string[]): void {
    if (!packages?.length) {
      return;
    }
    // 在ohmurl场景下，packages中的dependencyKey需要与packageName保持一致，所以，这里可以当做packageName使用
    packages.forEach((pkgName) => {
      const dependency = pkgName2DepMap.get(pkgName);
      if (!dependency?.isByteCodeHarDependency()) {
        return;
      }
      const pkgContextInfo = this.pkgContextInfos[dependency.getPackageName()];
      if (!pkgContextInfo) {
        this._log.debug(`Can not find package context information with package name: ${dependency.getPackageName()}`);
        return;
      }
      this.declarationEntry.push(generateOhmUrl(pkgContextInfo));
    });
  }

  private shouldCollectDeclarationEntry(): boolean {
    // 不使用新ohmurl，不需要处理
    if (!this.useNormalizedOHMUrl) {
      return false;
    }
    return this.isHapOrHsp();
  }

  private processDeclarationEntry(): void {
    if (!this.shouldCollectDeclarationEntry()) {
      return;
    }
    const dependencies = this.service.getHarDependencies();
    const pkgName2DepMap = dependencies.reduce((map, dependency) => {
      map.set(dependency.getPackageName(), dependency);
      return map;
    }, new Map<string, Dependency>());
    dependencies.forEach((dependency) => {
      this.collectByteCodeHarDeclarationEntry(dependency, pkgName2DepMap);
    });
    const runtimeOnlyObj = this.targetService.getBuildOption()?.arkOptions?.runtimeOnly;
    this.collectRuntimeDynamicImportByteCodeHarDeclarationEntry(pkgName2DepMap, runtimeOnlyObj?.packages);
  }

  private collectMockFileEntry(modulePath: string, mockConfigJson5: string) {
    if (!fse.existsSync(mockConfigJson5)) {
      return;
    }
    const mockConfig = parseJsonFile(mockConfigJson5, false);
    if (!mockConfig) {
      return;
    }
    Object.values(mockConfig).forEach((value: any) => {
      const source = value.source;
      if (source) {
        const mockSourceFilePath = path.resolve(modulePath, source);
        if (fse.existsSync(mockSourceFilePath)) {
          this.compileEntry.push(mockSourceFilePath);
        }
      }
    });
  }

  private logBuildError(cause: string, detail: string) {
    log._buildError(cause)._detail(detail)._printErrorAndExit();
  }

  /**
   * 校验规则ability在module.json5下的extensionAbilities数组中存在对应名称的name，
   * 其次对应name的type必须为form，该form ability对应的卡片配置文件下存在一个对应name的form
   *
   * @param intent
   * @param extensionMap
   * @param cause
   * @param detail
   * @private
   */
  private extensionAbilitiesValidate(intent: any, extensionMap: Map<string, any>, cause: string, detail: string) {
    if (intent.form === undefined || intent.form.ability === undefined) {
      return;
    }
    const formAbilityName = intent.form.ability;

    const hasFormAbilityInExtensionMap = extensionMap.has(formAbilityName) && extensionMap.get(formAbilityName).type === 'form';

    if (hasFormAbilityInExtensionMap) {
      return;
    }

    log.printErrorExit(
      'INSIGHT_INTENT_INVALID_FORM_ABILITY_NAME',
      [formAbilityName, this.insightIntentJsonPath],
      [[formAbilityName]]
    );
  }

  /**
   * formName规则校验，formName需在 form_config.json 中配置
   * @param intent 意图
   * @param formsNames form_config.json中配置的name全集
   * @private
   */
  private intentFormNameValidate(intent: any, formsNames: string[]) {
    const formName = intent.form?.formName;

    if (formName === undefined) {
      return;
    }
    if (!formsNames.length || !formsNames.includes(formName)) {
      this._log.printErrorExit('INVALID_FORM_NAME_%S', [formName]);
    }
  }

  /**
   * uiAbility/ability字段的校验
   * serviceExtension/ability字段校验，
   * 校验规则ability在module.json5下的extensionAbilities数组中存在对应名称的name，
   * 其次对应name的type必须为service
   *
   * @param intent
   * @param abilitiesSet
   * @param extensionMap
   * @param cause
   * @param detail
   * @private
   */
  private validateServiceExtensionAbility(intent: any, abilitiesSet: Set<string>, extensionMap: Map<string, any>, cause: string, detail: string) {
    if (!(intent.uiAbility === undefined || intent.uiAbility.ability === undefined)) {
      const curAbility = intent.uiAbility.ability;
      if (curAbility !== undefined) {
        if (!abilitiesSet.has(curAbility)) {
          log.printErrorExit(
            'INSIGHT_INTENT_INVALID_ABILITY_NAME',
            [curAbility, this.insightIntentJsonPath],
            [[curAbility]]
          );
        }
      }
    }

    if (intent.serviceExtension === undefined || intent.serviceExtension.ability === undefined) {
      return;
    }
    const serviceAbilityName = intent.serviceExtension.ability;

    const hasServiceAbilityInExtensionMap = extensionMap.has(serviceAbilityName) && extensionMap.get(serviceAbilityName)?.type === 'service';

    if (hasServiceAbilityInExtensionMap) {
      return;
    }
    log.printErrorExit(
      'INSIGHT_INTENT_INVALID_SERVICE_EXTENSION_ABILITY_NAME',
      [serviceAbilityName, this.insightIntentJsonPath],
      [[serviceAbilityName]]
    );
  }

  /**
   * ability字段在module.json中的abilities或extensionAbilities中是否存在
   *
   * @param intent
   * @param abilitiesSet
   * @param extensionMap
   * @param cause
   * @param detail
   * @private
   */
  private uiExtensionValidate(intent: any, abilitiesSet: Set<string>, extensionMap: Map<string, any>, cause: string, detail: string) {
    if (intent.uiExtension === undefined || intent.uiExtension.ability === undefined) {
      return;
    }
    const uiExtensionName = intent.uiExtension.ability;
    if (!(abilitiesSet.has(uiExtensionName) || extensionMap.has(uiExtensionName))) {
      log.printErrorExit(
        'INSIGHT_INTENT_INVALID_UI_EXTENSION_ABILITY_NAME',
        [uiExtensionName, this.insightIntentJsonPath],
        [[uiExtensionName]]
      );
    }
  }

  /**
   * insight_intent.json文件的业务校验
   *
   * @private
   */
  private validateForInsightIntentJson() {
    let cause = '';
    let detail = '';

    // 校验srcEntry是否真实存在,srcEntry的后缀要是ets
    for (const srcEntry of this.compileEntry) {
      if (!fse.existsSync(srcEntry)) {
        cause = `Cannot find the file under the specified path '${srcEntry}'.`;
        detail = 'Please check if the file in the path exists.';
        log.printErrorExit('FILE_NOT_EXIST', [srcEntry]);
      }

      if (!srcEntry.endsWith('.ets')) {
        cause = `The file must end with '.ets' in '${srcEntry}'.`;
        detail = 'Please check if the file name is correct.';
        log.printErrorExit('FILE_NO_END_WITH_ETS', [srcEntry, this.insightIntentJsonPath]);
      }
    }

    // 校验规则ability在module.json5下的abilities数组中存在对应名称的name
    const abilitiesSet: Set<string> = new Set();
    const moduleJson5 = parseJsonFile(this.moduleJson5Path, false);
    if (moduleJson5.module.abilities !== undefined) {
      for (const ability of moduleJson5.module.abilities) {
        abilitiesSet.add(ability.name);
      }
    }
    const extensionMap: Map<string, any> = new Map();
    if (moduleJson5.module.extensionAbilities !== undefined) {
      for (const extension of moduleJson5.module.extensionAbilities) {
        extensionMap.set(extension.name, extension);
      }
    }

    if (this.insightIntentJson !== null) {
      const formsNames = this.getFormConfigNames();
      for (const intent of this.insightIntentJson.insightIntents ?? []) {
        // serviceExtension/ability字段校验，
        this.validateServiceExtensionAbility(intent, abilitiesSet, extensionMap, cause, detail);

        // form/ability字段校验
        this.extensionAbilitiesValidate(intent, extensionMap, cause, detail);

        // form/formName字段校验
        this.intentFormNameValidate(intent, formsNames);

        // uiExtension的校验
        this.uiExtensionValidate(intent, abilitiesSet, extensionMap, cause, detail);
      }
    }
  }

  private getFormConfigNames() {
    const formConfigPath = path.resolve(this.pathInfo.getModuleSrcMainResourceBaseProfilePath(), BuildArtifactConst.FORM_CONFIG_JSON);
    if (fse.existsSync(formConfigPath)) {
      const formConfigJson = Json5Reader.getJson5Obj(formConfigPath) as ConfigJson.AbilitiesObj;
      return formConfigJson?.forms?.map((form) => form.name) ?? [];
    }
    return [];
  }

  /**
   *  读取InsightIntent.json中的srcEntry
   */
  private readInsightIntentSrcEntry(): string[] {
    const curSet: Set<string> = new Set();
    let srcEntryPath = '';
    if (fse.existsSync(this.insightIntentJsonPath)) {
      const insightIntentDataJson = parseJsonFile(this.insightIntentJsonPath, false);
      this.insightIntentJson = insightIntentDataJson;
      const srcMainPath = this.moduleSrcMainPath;

      // 遍历获取每个意图API的srcEntry,新意图框架下insightIntents和insightIntentsSrcEntry都不是必选
      for (const intent of [...(insightIntentDataJson.insightIntents ?? []), ...(insightIntentDataJson.insightIntentsSrcEntry ?? [])]) {
        const srcEntry = intent.srcEntry;
        srcEntryPath = path.resolve(srcMainPath, srcEntry);
        curSet.add(srcEntryPath);
      }
    }
    return Array.from(curSet);
  }

  /**
   * 检查当前Sdk版本是否支持Aot，只检查ohos场景
   * @private
   */
  private checkAotCompatibleSdkVersion() {
    if (!this.sdkInfo.isOhos) {
      return;
    }
    const supportAotVersion = SdkVersionEnum.SUPPORT_AOT_OHOS;
    const etsSdkVersion: string = this.sdkInfo.getEtsComponentVersion();
    if (etsSdkVersion === '') {
      return;
    }
    const curAotVersion = new SdkVersion(etsSdkVersion);
    if (supportAotVersion.isHigherThan(curAotVersion)) {
      const projectType = 'OpenHarmony SDK';
      this._log.printErrorExit('AOT_COMPILING_UNSUPPORTED_SDK_VERSION', [curAotVersion.getVersion(), supportAotVersion.getVersion()], [[projectType]]);
    }
  }

  private handleAotFields(): Record<string, string> {
    const anBuildMode = this.targetService.getAnBuildMode();
    this.warnAnBuildMode();

    // api10已经使能aot编译，不需要检查sdk版本
    if (anBuildMode && this.compileApiVersion === ApiVersion.API_VERSION_9) {
      this.checkAotCompatibleSdkVersion();
    }

    const aotParams: AotConfigsParams = {
      anBuildMode,
      apPath: this.apPath,
      apiVersion: this.compileApiVersion,
      fallbackAnBuild: this.fallbackAnBuild,
    };

    // 根据api版本、anBuildMode和apPath的值来获取返回aot值的策略模式
    return this.getAotStrategy(aotParams);
  }

  private warnAnBuildMode(): void {
    const apiVersion = this.targetData.getCompileApiVersion();
    const aotCompileMode = this.targetService.getBuildOption()?.arkOptions?.aotCompileMode ?? this.targetService.getBuildOption()?.aotCompileMode;
    const hostPGO = this.targetService.getBuildOption().arkOptions?.hostPGO;
    switch (apiVersion) {
      case ApiVersion.API_VERSION_9:
        if (hostPGO !== undefined) {
          log.warn('Field "hostPGO" is not supported in API version 9. The value of this field will be ignored.');
        }
        break;
      case ApiVersion.API_VERSION_10:
      default:
        if (aotCompileMode !== undefined) {
          log.warn('Field "aotCompileMode" is not supported since API version 10. The value of this field will be ignored.');
        }
        if (this.sdkInfo.isOhos && !this.sdkInfo.checkAotFixedSdkVersion()) {
          const projType = 'SDK > OpenHarmony';
          log
            ._buildError(
              'Current version of sdk has a bug when using AoT compiling. The compiling will continue ' +
                'with AoT compiling function disabled. ' +
                `Current SDK version is ${this.sdkInfo.getEtsComponentVersion()}, but the lowest fixed SDK version ` +
                `is ${SdkVersionEnum.FIXED_AOT_OHOS.getVersion()}.`,
            )
            ._detail(`Update SDK to the latest version by going to Tools > SDK Manager > ${projType}. Open SDK Manager`)
            ._printWarn(this.moduleName);
        }
        break;
    }
  }

  private getHarNameOhmMap(): object {
    if (!this.targetService.isByteCodeHar()) {
      return {};
    }
    // 阻断字节码HAR和npm三方库编译逻辑
    if (this.targetService.isBundledDependencies()) {
      const npmAndByteHarDeps = this.isByteCodeHarOptimize ?
        this.service.getRootOtherDependencies().concat(this.service.getRootByteCodeHarDependencies()) :
        this.service.getOtherDependencies().concat(this.service.getHarDependencies().filter((dept) => dept.isByteCodeHarDependency()));
      return this.getOHMUrlMap(npmAndByteHarDeps, this.pkgContextInfos);
    }

    const directDependencies = this.isByteCodeHarOptimize ? this.service.getAllDirectDependencies() : this.service.getDirectDependencies();
    const dependencies = directDependencies.filter((dependency) => {
      return dependency.getDependencyType() !== DependencyType.DEPENDENCY_TYPE_HSP;
    });
    return this.getOHMUrlMap(dependencies, this.pkgContextInfos);
  }

  private getHspDependencies() {
    const shouldGetAllHsps = InjectUtil.isPreviewProcess() || InjectUtil.isLocalTest();
    if (this.isByteCodeHarOptimize) {
      return shouldGetAllHsps ? this.service.getAllHspDependencies() : this.service.getRootHspDependencies();
    }

    // 如果当前是预览或者localTest，需要收集依赖链中所有hsp
    if (shouldGetAllHsps) {
      const dependencyManager = new DependencyManager(this.projectModel.isFaMode(), this.moduleModel, this.projectModel);
      const { npmDependencies } = dependencyManager.collectAllDependencies();
      return npmDependencies.filter((dependency) => {
        return dependency.getDependencyType() === DependencyType.DEPENDENCY_TYPE_HSP;
      });
    }

    return this.service.getHspDependencies();
  }

  /**
   * 生成hspNameOhmMap对象
   * @private
   */
  private getHspNameOhmMap(): object {
    let hspNameOhmMap: { [key: string]: string } = {};
    const dependencies = this.getHspDependencies();

    if (this.useNormalizedOHMUrl) {
      hspNameOhmMap = this.getOHMUrlMap(dependencies, this.pkgContextInfos);
    } else {
      dependencies.forEach((dependency) => {
        const moduleName = dependency.getDependencyName();
        const hspDependencyModuleName = this.getHspDependencyModuleName(dependency);
        const hspDependencyPackageMainName = this.getHspDependencyPackageMainName(dependency);
        if (hspDependencyPackageMainName !== '') {
          hspNameOhmMap[moduleName] = `@bundle:${hspDependencyModuleName}${hspDependencyPackageMainName}`;
        }
      });
    }
    return hspNameOhmMap;
  }

  private getHspResourcesMap(): object {
    const hspResourcesMap: { [key: string]: string } = {};
    const depHspTargets = HspTargetUtils.calDepHspTargets(this.targetService);
    depHspTargets.forEach((targetData, hspName) => {
      const resourcesPath = path.resolve(targetData.getPathInfo().getIntermediatesRes(), BuildArtifactConst.RESOURCE_TABLE_TXT);
      if (fse.existsSync(resourcesPath)) {
        hspResourcesMap[targetData.getModuleModel().getName()] = resourcesPath;
      } else {
        this._log.debug(`The ResourceTable.txt in ${targetData.getPathInfo().getModulePath()} does not exist.`);
      }
    });
    this.service.getHspDependencies().forEach((dependency) => {
      const dependencyName = dependency.getDependencyName();
      let resourcesPath;
      if (!dependency.isLocal()) {
        resourcesPath = path.resolve(dependency.getDependencyRootPath(), BuildArtifactConst.RESOURCE_TABLE_TXT);
      }
      if (resourcesPath && fse.existsSync(resourcesPath)) {
        hspResourcesMap[dependencyName] = resourcesPath;
      } else {
        this._log.debug(`The ResourceTable.txt in ${dependency.getDependencyRootPath()} does not exist.`);
      }
    });
    return hspResourcesMap;
  }

  private getOHMUrlMap(dependencies: Dependency[], pkgInfoObj: any) {
    const hspNameOhmMap: { [key: string]: string } = {};
    const packageNames = dependencies.map((dependence) => dependence.getPackageName());
    Object.values(pkgInfoObj).forEach((pkgInfo: any) => {
      if (packageNames.includes(pkgInfo.packageName)) {
        const dependencyInfo = dependencies.filter((dependence) => dependence.getPackageName() === pkgInfo.packageName);
        hspNameOhmMap[dependencyInfo[0].getDependencyName()] = generateOhmUrl(pkgInfo);
      }
    });
    return hspNameOhmMap;
  }

  /**
   * 共享hsp包配置loader.json的hspNameOhmMap时，获取package.json的main字段，如main字段为空则试图获取types字段
   * @param dependency
   */
  private getHspDependencyPackageMainName(dependency: Dependency): string {
    const packageSrcPath = path.resolve(dependency.getDependencyRootPath(), './src/main');
    let packageMainFilePath;
    if (Json5Reader.getJson5Obj(dependency.getPackageFilePath()).main) {
      packageMainFilePath = dependency.getDependencyMainFilePath();
    } else {
      packageMainFilePath = dependency.getDependencyTypesFilePath();
    }
    let packageMainName;
    if (packageMainFilePath.startsWith(packageSrcPath)) {
      packageMainName = packageMainFilePath.replace(packageSrcPath, '');
    } else if (packageMainFilePath.startsWith(dependency.getDependencyRootPath())) {
      packageMainName = packageMainFilePath.replace(dependency.getDependencyRootPath(), '');
    }
    if (packageMainName) {
      return removeSuffix(packageMainName);
    }
    log
      ._buildError(
        `The "main" or "types" field of hsp module ${dependency.getPackageName()} must be under the
      root path of hsp module or under src/main path. Please confirm.`,
      )
      ._file(dependency.getPackageFilePath())
      ._printWarn(this.moduleName);
    return '';
  }

  /**
   * 共享hsp包配置loader.json的hspNameOhmMap时，获取module.json5的name字段
   * @param dependency
   */
  private getHspDependencyModuleName(dependency: Dependency): string {
    const localModuleList: string[] = this.service.getHspModuleDependencyPaths();
    let hspModuleJson: AppOptObj & ModuleOptObj;
    const moduleJson5: string = path.resolve(dependency.getDependencyRootPath(), 'src', 'main', 'module.json5');
    const moduleJson: string = path.resolve(dependency.getDependencyRootPath(), 'src', 'main', 'module.json');
    let bundleName: string;
    const appOptFromConfig: AppOpt = cloneDeep(projectOhosConfigManager.getOverrides()?.appOpt);
    if (localModuleList.includes(dependency.getDependencyRootPath())) {
      hspModuleJson = Json5Reader.getJson5Obj(moduleJson5);
      bundleName = appOptFromConfig?.bundleName ?? this.targetData.getProduct().bundleName ?? this.projectModel.getDefaultBundleName();
    } else {
      if (fse.existsSync(moduleJson)) {
        hspModuleJson = getJson5Obj(moduleJson);
        bundleName = hspModuleJson.app.bundleName;
      } else {
        hspModuleJson = Json5Reader.getJson5Obj(moduleJson5);
        bundleName = appOptFromConfig?.bundleName ?? this.targetData.getProduct().bundleName ?? this.projectModel.getDefaultBundleName();
      }
    }

    return `${bundleName}/${hspModuleJson.module.name}`;
  }

  /**
   * 使用策略模式，
   *
   * @param {AotConfigsParams} params
   * @returns {Record<string, string>}
   * @private
   */
  private getAotStrategy(params: AotConfigsParams): Record<string, string> {
    const { apiVersion, anBuildMode, apPath, fallbackAnBuild } = params;
    const isApPathExist = apPath !== undefined && fse.pathExistsSync(apPath);
    const isValidSuffix = apPath !== undefined && apPath.endsWith('ap');
    const aotStrategies: TStrategy<(conf: AotConfigsParams) => Record<string, string> | void>[] = [
      {
        name: AotRolesEnum.WITH_EMPTY,
        condition: fallbackAnBuild,
        strategy: this.withEmpty,
      },
      {
        name: AotRolesEnum.ERROR_MISMATCH_AOT_COMPILE_MODE,
        condition: apiVersion === ApiVersion.API_VERSION_9 && anBuildMode !== AotCompileModeEnum.AOT_PARTIAL && apPath !== undefined,
        strategy: this.mismatchAotCompileMode,
      },
      {
        name: AotRolesEnum.ERROR_PARTIAL_EMPTY_PATH,
        condition: apiVersion === ApiVersion.API_VERSION_9 && anBuildMode === AotCompileModeEnum.AOT_PARTIAL && apPath === undefined,
        strategy: this.partialEmptyPath,
      },
      {
        name: AotRolesEnum.ERROR_INVALID_SUFFIX,
        condition: apPath !== undefined && !isValidSuffix,
        strategy: this.invalidSuffix,
      },
      {
        name: AotRolesEnum.ERROR_INVALID_PATH,
        condition: anBuildMode === AotCompileModeEnum.AOT_PARTIAL && !isApPathExist,
        strategy: this.invalidPath,
      },
      {
        name: AotRolesEnum.WITH_EMPTY,
        condition:
          ((apiVersion === ApiVersion.API_VERSION_9 && apPath === undefined) || apiVersion >= ApiVersion.API_VERSION_10) &&
          anBuildMode === AotCompileModeEnum.AOT_NULL,
        strategy: this.withEmpty,
      },
      {
        name: AotRolesEnum.WITH_AP_PATH,
        condition:
          ((apiVersion === ApiVersion.API_VERSION_9 && anBuildMode === AotCompileModeEnum.AOT_PARTIAL) || apiVersion >= ApiVersion.API_VERSION_10) &&
          isApPathExist &&
          isValidSuffix,
        strategy: this.withApPath,
      },
      {
        name: AotRolesEnum.WITHOUT_AP_PATH,
        condition: apiVersion === ApiVersion.API_VERSION_9 && anBuildMode === AotCompileModeEnum.AOT_TYPE && apPath === undefined,
        strategy: this.withoutApPath,
      },
      {
        name: AotRolesEnum.WITHOUT_AP_PATH,
        condition: apiVersion >= ApiVersion.API_VERSION_10 && anBuildMode === AotCompileModeEnum.AOT_TYPE && !isApPathExist,
        strategy: this.withoutApPath,
      },
    ];

    const strategy = getStrategy(aotStrategies, () => {
      return {};
    });
    return strategy.bind(this)(params) as Record<string, string>;
  }

  /**
   * 当ap路径存在时返回的loader.json片段
   * @param {AotConfigsParams} conf
   * @private
   */
  private withApPath(conf: AotConfigsParams) {
    fse.emptyDirSync(this.tempApDir);
    fse.copyFileSync(conf.apPath!, this.tempApPath);
    return {
      anBuildOutPut: this.anBuildOutPutPath,
      anBuildMode: conf.anBuildMode,
      apPath: conf.apPath!,
    };
  }

  /**
   * 当ap路径不存在时返回的loader.json片段
   * @param {AotConfigsParams} conf
   * @private
   */
  private withoutApPath(conf: AotConfigsParams) {
    return {
      anBuildOutPut: this.anBuildOutPutPath,
      anBuildMode: conf.anBuildMode,
    };
  }

  /**
   * 当不使能aot编译时，返回空片段
   * @returns {{}}
   * @private
   */
  private withEmpty() {
    return {};
  }

  /**
   * api9上配置了apPath但没有配置aotCompileMode，需要报错
   * @private
   */
  private mismatchAotCompileMode() {
    this._log.printErrorExit('MISMATCH_AOT_COMPILE_MODE', [this.moduleModel.getProfilePath()]);
  }

  /**
   * api9上配置了partial模式时没有配置apPath，需要报错
   * @private
   */
  private partialEmptyPath() {
    this._log.printErrorExit('PARTIAL_EMPTY_PATH', [this.moduleModel.getProfilePath()]);
  }

  /**
   * 配置了partial模式时apPath路径不存在，需要报错
   * @private
   */
  private invalidPath() {
    this._log.printErrorExit('PARTIAL_INVALID_PATH', [this.moduleModel.getProfilePath(), this.apPath]);
  }

  /**
   * 路径非以.ap后缀结尾，需要报错
   * @private
   */
  private invalidSuffix() {
    this._log.printErrorExit('PARTIAL_INVALID_SUFFIX', [this.moduleModel.getProfilePath()]);
  }

  /**
   * 将appStartup的startupTask中定义的srcEntry和configEntry写入compileEntry加载到编译流程中
   * 先写本模块的，再写依赖的har模块的
   * @param appStartupPath
   * @private
   */
  private processAppStartupConfig(appStartupPath: string | undefined): void {
    if (appStartupPath !== undefined && fse.existsSync(appStartupPath)) {
      const appStartupObj: StartupOptions = getJson5Obj(appStartupPath);
      const moduleSrcMain = path.resolve(this.module.getNodeDir(), BuildDirConst.SRC, BuildDirConst.MAIN);
      // 没有在intermediateTempStartupFilePath文件中生成configEntry绝对路径，需要在这里单独处理一下
      if (appStartupObj.configEntry) {
        this.compileEntry.push(path.resolve(moduleSrcMain, appStartupObj.configEntry));
      }
    }
    const startupMergedOptions: StartupOptions | undefined = getJson5Obj(this.intermediateTempStartupFilePath);
    if (startupMergedOptions !== undefined) {
      startupMergedOptions.startupTasks?.forEach((startupTask) => {
        if (startupTask.srcEntryAbsolutePath !== undefined) {
          this.compileEntry.push(startupTask?.srcEntryAbsolutePath);
        }
      });
    }
  }

  /**
   * 处理dynamic import
   * @private
   */
  private processDynamicImport(): void {
    // 处理所有har依赖的间接依赖，字节码har不需要处理
    if (!this.targetService.isByteCodeHar()) {
      this.processIndirectDependency(this.service.getHarDependencies());
    }

    const runtimeOnlyObj = this.targetService.getBuildOption()?.arkOptions?.runtimeOnly;
    if (!runtimeOnlyObj) {
      return;
    }
    if (runtimeOnlyObj.sources) {
      // 相对路径形式的文件或文件夹的动态导入转化成绝对路径后写入compileEntry
      const curModuleNodeDir = this.module.getNodeDir();
      runtimeOnlyObj.sources.forEach((dynamicImport) => {
        const absolutePath = path.resolve(curModuleNodeDir, dynamicImport);
        const fileStat = fse.statSync(absolutePath);
        if (fileStat.isFile()) {
          this.compileEntry.push(absolutePath);
        }
        if (fileStat.isDirectory()) {
          this.processDirectoryImport(absolutePath);
        }
      });
    }

    // 字节码har不需要处理packages
    if (runtimeOnlyObj.packages && !this.targetService.isByteCodeHar()) {
      // 文件形式的动态导入找到该文件的入口文件绝对路径写入compileEntry,同时生成dynamicImportLibInfo
      runtimeOnlyObj.packages.forEach((dynamicImport) => {
        if (this.isHarDependency(dynamicImport)) {
          // 处理本地,远程har形式的dynamic import
          this.processHarDynamicImport(dynamicImport, this.dynamicImportLibInfo);
        } else {
          // 处理非har(hsp,npm,.so等)形式的dynamic import
          this.processOtherDynamicImport(dynamicImport, this.dynamicImportLibInfo);
        }
      });
    }
  }

  /**
   * 处理本地、远程har依赖形式dynamicImport
   * @param dynamicImport
   * @param dynamicImportLibInfo
   * @private
   */
  private processHarDynamicImport(dynamicImport: string, dynamicImportLibInfo: Record<string, DynamicImportObj>): void {
    this.service.getHarDependencies().forEach((dependency) => {
      const dependencyName = dependency.getDependencyName();
      if (dependencyName === dynamicImport) {
        // 仅收集本地、远程har依赖形式dynamicImport，其中字节码HAR只有声明文件
        const dependencyMainFilePath = dependency.isByteCodeHarDependency() ? dependency.getDependencyTypesFilePath() : dependency.getDependencyMainFilePath();
        const dependencyPkgFilePath = dependency.getPackageFilePath();
        if (this.existInDynamicImportLibsInfo(dynamicImport)) {
          // 如果dynamicImportLibsInfo中已存在同名依赖名对象 则跳过写入
          return;
        }
        const newDynamicImportLibInfo = {
          [dependencyName]: {
            hostModulesInfo: [
              {
                hostDependencyName: dependencyName,
                hostModuleName: this.moduleModel.getName(), // 依赖该har包的模块名
              },
            ],

            // 该har包自身模块名,本地依赖取绝对路径的module.json5->module->name;远程依赖取绝对路径oh-package.json5->name
            moduleName: this.getHarDependencyModuleName(dependency, dynamicImport),
            entryFilePath: dependencyMainFilePath,
            isLocalDependency: dependency.isLocal(),
            pkgPath: dependencyPkgFilePath.substring(0, dependencyPkgFilePath.lastIndexOf(path.sep)),
          },
        };
        Object.assign(dynamicImportLibInfo, newDynamicImportLibInfo);

        // 如果该依赖为字节码HAR，不用收集
        if (dependency.isByteCodeHarDependency()) {
          return;
        }
        this.compileEntry.push(dependencyMainFilePath);

        // 对src/main/ets下的代码文件进行收集
        this.collectDepEtsFolderFilesEntry(dependency);
      }
    });
  }

  /**
   * 处理npm/hsp/.so形式dynamic import
   * @param dynamicImport
   * @param dynamicImportLibInfo
   * @private
   */
  private processOtherDynamicImport(dynamicImport: string, dynamicImportLibInfo: Record<string, DynamicImportObj>): void {
    // 获取模块dynamicImport路径
    const moduleOhModulesPath = path.resolve(this.moduleModel.getModule().getNodeDir(), CommonConst.OH_MODULES, dynamicImport);
    const projectOhModulesPath = path.resolve(this.projectRootPath, CommonConst.OH_MODULES, dynamicImport);
    const dynamicImportOhModulesPath: string = fse.existsSync(moduleOhModulesPath)
      ? moduleOhModulesPath
      : fse.existsSync(projectOhModulesPath)
        ? projectOhModulesPath
        : '';
    if (dynamicImportOhModulesPath === '') {
      return;
    }

    // 获取软链接真实路径 解析oh-package.json5获取入口文件
    const realDependencyPath = fse.realpathSync(dynamicImportOhModulesPath);
    if (!fse.existsSync(realDependencyPath)) {
      return;
    }
    const dynamicImportOhPkgJsonPath = ohPackageLoader.getNodeOhPackagePath(path.resolve(dynamicImportOhModulesPath, CommonConst.OH_PACKAGE_JSON5));
    const dynamicImportOhPkgObj: OhPackageJsonOpt = getJson5Obj(dynamicImportOhPkgJsonPath);
    if (!dynamicImportOhPkgObj) {
      return;
    }
    const dynamicImportEntryMainFile = this.getEntryMainFilePath(realDependencyPath, dynamicImportOhPkgObj);
    const realDependencySrcMainPath = path.resolve(realDependencyPath, BuildDirConst.SRC, BuildDirConst.MAIN);
    const isLocalDependency = DependencyManager.isLocalDependencyForSo(dynamicImportEntryMainFile);
    const dynamicImportModuleJsonPath = isLocalDependency
      ? path.resolve(realDependencySrcMainPath, CommonConst.MODULE_JSON5)
      : path.resolve(realDependencySrcMainPath, CommonConst.MODULE_JSON);

    // moduleName:.so/npm直接取oh-package.json5->name
    let dynamicImportModuleName = dynamicImportOhPkgObj.name;
    let dynamicImportModuleType: string | undefined;
    if (fse.existsSync(dynamicImportModuleJsonPath)) {
      const dynamicImportJsonObj: ModuleOptObj = getJson5Obj(dynamicImportModuleJsonPath);
      if (!dynamicImportJsonObj) {
        return;
      }
      dynamicImportModuleType = dynamicImportJsonObj.module.type;
      if (this.isHspDependency(dynamicImport)) {
        // moduleName:hsp本地取module.json5/远程取module.json->module->name
        dynamicImportModuleName = dynamicImportJsonObj.module.name;
      }
    }

    if (!dynamicImportModuleType && dynamicImportModuleType !== ModuleType.Shared && !ValidateRegExp.SO_DEPENDENCY_REG_EXP.test(dynamicImport)) {
      // 非.so,hsp形式的动态导入(har,npm)才写入compileEntry
      this.compileEntry.push(dynamicImportEntryMainFile);
    }

    if (this.existInDynamicImportLibsInfo(dynamicImport)) {
      return;
    }
    const newDynamicImportLibInfo = {
      [dynamicImport]: {
        hostModulesInfo: [
          {
            hostDependencyName: dynamicImport,
            hostModuleName: this.moduleModel.getName(), // 依赖该hsp,.so,npm包的模块名
          },
        ],

        moduleName: dynamicImportModuleName,
        entryFilePath: dynamicImportEntryMainFile,
        isLocalDependency,
        pkgPath: realDependencyPath,
      },
    };
    Object.assign(dynamicImportLibInfo, newDynamicImportLibInfo);
  }

  private getLocalDependencyRuntimeOnly(dependency: Dependency) {
    if (!dependency.isLocal()) {
      return undefined;
    }
    const moduleName = dependency.getModuleJsonObj()?.module.name ?? dependency.getPackageName();
    const dependencyTargetName = HarTargetUtil.calDepHarTargets(this.targetService).get(moduleName) ?? 'default';
    const targetBuildOption = buildOptionManager.getTargetBuildOption(moduleName, dependencyTargetName);
    return targetBuildOption.arkOptions?.runtimeOnly;
  }

  private getLocalDependencyDynamicImportList(dependency: Dependency) {
    return this.collectDynamicImport(this.getLocalDependencyRuntimeOnly(dependency));
  }

  private getRemoteDependencyDynamicImportList(dependency: Dependency) {
    const packageFilePath = dependency.getPackageFilePath();
    const remoteOhPkgJsonObj: OhPackageJsonOpt = getJson5Obj(packageFilePath);
    if (!remoteOhPkgJsonObj) {
      return [];
    }
    const runtimeOnlyObj = remoteOhPkgJsonObj.metadata?.runtimeOnly;
    return this.collectDynamicImport(runtimeOnlyObj);
  }

  /**
   * 处理间接依赖
   * @private
   */
  private processIndirectDependency(dependencyList: Dependency[]): void {
    dependencyList.forEach((dependency) => {
      const dynamicImportList = dependency.isLocal()
        ? this.getLocalDependencyDynamicImportList(dependency)
        : this.getRemoteDependencyDynamicImportList(dependency);
      if (dynamicImportList.length !== 0) {
        this.processIndirectDependencyInfo(dependency, dynamicImportList);
      }
    });
  }

  /**
   * 收集package/path数组中的所有dynamicImport
   * @param runtimeOnlyObj
   * @private
   */
  private collectDynamicImport(runtimeOnlyObj: RuntimeOnlyObj | undefined): string[] {
    return [...(runtimeOnlyObj?.sources ?? []), ...(runtimeOnlyObj?.packages ?? [])];
  }

  /**
   * 处理间接依赖的dynamicImport相关信息 npm包不作处理
   * @param dependency
   * @param dynamicImportList
   * @private
   */
  private processIndirectDependencyInfo(dependency: Dependency, dynamicImportList: string[]): void {
    dynamicImportList.forEach((dynamicImport) => {
      if (this.isHarDependency(dynamicImport)) {
        // 处理har类型间接依赖
        this.writeIndirectDependencyInfo(this.service.getHarDependencies(), dynamicImport);
      }

      if (this.isHspDependency(dynamicImport)) {
        // 处理hsp类型间接依赖
        this.writeIndirectDependencyInfo(this.service.getHspDependencies(), dynamicImport);
      }

      if (ValidateRegExp.SO_DEPENDENCY_REG_EXP.test(dynamicImport)) {
        // 处理.so类型间接依赖
        this.processIndirectSoDependencyInfo(dependency, dynamicImport);
      }

      if (ValidateRegExp.RELATIVE_PATH_REG_EXP.test(dynamicImport)) {
        const absolutePath = path.resolve(dependency.getDependencyRootPath(), dynamicImport);
        if (!fse.existsSync(absolutePath)) {
          return;
        }

        const pathStats = fse.statSync(absolutePath);
        if (pathStats.isFile()) {
          this.compileEntry.push(absolutePath);
        }
        if (pathStats.isDirectory()) {
          this.processDirectoryImport(absolutePath);
        }
      }
    });
  }

  /**
   * 处理文件夹相对路径形式的动态import
   * @param absolutePath
   * @private
   */
  private processDirectoryImport(absolutePath: string): void {
    FileUtil.getAllFilesFromFolder(absolutePath).forEach((filePath) => {
      if (ValidateRegExp.DYNAMIC_IMPORT_FILE_SUFFIX_REG_EXP.test(FileUtil.getFileSuffix(filePath)) && fse.existsSync(filePath)) {
        this.compileEntry.push(filePath);
      }
    });
  }

  /**
   * 处理.so类型的间接依赖的dynamicImportLibInfo
   * @param dependency
   * @param dynamicImport
   * @private
   */
  private processIndirectSoDependencyInfo(dependency: Dependency, dynamicImport: string): void {
    const dependencyRootPath = dependency.getDependencyRootPath();
    const dependencyMainFilePath = dependency.getDependencyMainFilePath();
    const dependencyPkgFilePath = dependency.getPackageFilePath();
    const isLocalDependency = DependencyManager.isLocalDependencyForSo(dependencyMainFilePath);

    if (this.existInDynamicImportLibsInfo(dynamicImport)) {
      return;
    }
    if (ValidateRegExp.SO_DEPENDENCY_REG_EXP.test(dynamicImport)) {
      let ohPkgJsonPath = isLocalDependency
        ? path.resolve(dependencyRootPath, CommonConst.OH_MODULES, dynamicImport, CommonConst.OH_PACKAGE_JSON5)
        : path.resolve(dependencyRootPath.substring(0, dependencyRootPath.lastIndexOf(path.sep)), dynamicImport, CommonConst.OH_PACKAGE_JSON5);
      ohPkgJsonPath = ohPackageLoader.getNodeOhPackagePath(ohPkgJsonPath);
      const ohPkgJsonObj: OhPackageJsonOpt = getJson5Obj(ohPkgJsonPath);
      if (!ohPkgJsonObj) {
        return;
      }
      const mainEntryFilePath = path.resolve(
        dependencyRootPath,
        BuildDirConst.SRC,
        BuildDirConst.MAIN,
        BuildDirConst.CPP_TYPES,
        dynamicImport,
        ohPkgJsonObj.types,
      );

      const newDynamicImportLibsInfo = {
        [dynamicImport]: {
          hostModulesInfo: [
            {
              hostDependencyName: dynamicImport,
              hostModuleName: this.getHostModuleName(dependency), // 直接依赖该.so的模块名
            },
          ],

          // .so取oh-package.json5->name
          moduleName: ohPkgJsonObj.name,
          entryFilePath: mainEntryFilePath,
          isLocalDependency,
          pkgPath: dependencyPkgFilePath.substring(0, dependencyPkgFilePath.lastIndexOf(path.sep)),
        },
      };
      Object.assign(this.dynamicImportLibInfo, newDynamicImportLibsInfo);
    }
  }

  /**
   * 写入compileEntry/compileEntryDir和dynamicImportLibInfo
   * @param dependencyList
   * @param dynamicImport
   * @private
   */
  private writeIndirectDependencyInfo(dependencyList: Dependency[], dynamicImport: string): void {
    dependencyList.forEach((dependency) => {
      if (dependency.getDependencyName() === dynamicImport) {
        const isHarDependency = this.isHarDependency(dynamicImport);
        if (isHarDependency) {
          this.collectDepEtsFolderFilesEntry(dependency);
        }
        const dependencyMainFilePath = dependency.getDependencyMainFilePath();
        const dependencyMainEntryFilePath = fse.existsSync(dependencyMainFilePath) ? dependencyMainFilePath : dependency.getDependencyTypesFilePath();
        if (!fse.existsSync(dependencyMainEntryFilePath)) {
          return;
        }

        // 字节码HAR不用写入
        if (isHarDependency && !dependency.isByteCodeHarDependency()) {
          const dependencyMainFileStat = fse.statSync(dependencyMainEntryFilePath);

          // 仅har依赖需要写入compileEntry,文件夹形式需遍历其下满足ets/ts后缀的文件写入
          if (dependencyMainFileStat.isFile()) {
            this.compileEntry.push(dependencyMainEntryFilePath);
          } else if (dependencyMainFileStat.isDirectory()) {
            FileUtil.getAllFilesFromFolder(dependencyMainEntryFilePath).forEach((filePath) => {
              if (ValidateRegExp.DYNAMIC_IMPORT_FILE_SUFFIX_REG_EXP.test(FileUtil.getFileSuffix(filePath))) {
                this.compileEntry.push(filePath);
              }
            });
          }
        }

        if (this.existInDynamicImportLibsInfo(dynamicImport)) {
          return;
        }

        const dependencyRootSrcMainPath = path.resolve(dependency.getDependencyRootPath(), BuildDirConst.SRC, BuildDirConst.MAIN);
        const moduleJsonPath = path.resolve(dependencyRootSrcMainPath, CommonConst.MODULE_JSON);
        const moduleJson5Path = path.resolve(dependencyRootSrcMainPath, CommonConst.MODULE_JSON5);
        const jsonFilePath = fse.existsSync(moduleJsonPath) ? moduleJsonPath : fse.existsSync(moduleJson5Path) ? moduleJson5Path : '';
        const moduleJsonObj: ModuleOptObj = getJson5Obj(jsonFilePath);
        if (!moduleJsonObj) {
          return;
        }
        const moduleType = moduleJsonObj.module.type;
        const moduleName =
          moduleType === ModuleType.Har
            ? this.getHarDependencyModuleName(dependency, dynamicImport)
            : moduleType === ModuleType.Shared
              ? moduleJsonObj.module.name
              : '';

        const dependencyPackageFilePath = dependency.getPackageFilePath();
        const newDynamicImportLibsInfo = {
          [dynamicImport]: {
            hostModulesInfo: [
              {
                hostDependencyName: dynamicImport,
                hostModuleName: this.moduleName, // 直接依赖该依赖包的模块名
              },
            ],

            // 间接依赖:本地/远程har:module.json5->module->name/oh-package.json5->name
            // 间接依赖:本地/远程hsp:module.json5/module.json->module->name
            moduleName,
            entryFilePath: dependencyMainEntryFilePath,
            isLocalDependency: dependency.isLocal(),
            pkgPath: dependencyPackageFilePath.substring(0, dependencyPackageFilePath.lastIndexOf(path.sep)),
          },
        };
        Object.assign(this.dynamicImportLibInfo, newDynamicImportLibsInfo);
      }
    });
  }

  /**
   * 获取依赖入口文件
   * @param realDependencyPath
   * @param dynamicImportOhPkgObj
   * @private
   */
  private getEntryMainFilePath(realDependencyPath: string, dynamicImportOhPkgObj: OhPackageJsonOpt): string {
    const nodeEntryFile = path.resolve(realDependencyPath, findNodeEntryFiles(dynamicImportOhPkgObj)[0]);
    if (fse.existsSync(nodeEntryFile)) {
      return nodeEntryFile;
    } else {
      // 如果入口文件不存在则需要解析oh-package.json5并读取main/types/index.js
      const primaryEntryFile = path.resolve(realDependencyPath, dynamicImportOhPkgObj.main ?? dynamicImportOhPkgObj.types ?? BuildArtifactConst.INDEX_JS);
      return fse.existsSync(primaryEntryFile) ? primaryEntryFile : '';
    }
  }

  /**
   * 获取har dependency的模块 模块名
   * @param dependency
   * @private
   */
  private getHostModuleName(dependency: Dependency): string {
    const dependencyRootPath = dependency.getDependencyRootPath();
    const moduleJsonPath = path.resolve(
      dependencyRootPath,
      BuildDirConst.SRC,
      BuildDirConst.MAIN,
      `${dependency.isLocal() ? CommonConst.MODULE_JSON5 : CommonConst.MODULE_JSON}`,
    );
    const moduleOptObj: ModuleOptObj = getJson5Obj(moduleJsonPath);
    if (!moduleOptObj) {
      return '';
    }
    return moduleOptObj.module?.name;
  }

  /**
   * 获取har依赖的dependencyInfo中的moduleName
   * 本地har取module.json5->module->name;远程har取oh-package.json5->name
   * @param dependency
   * @param dynamicImport
   * @private
   */
  private getHarDependencyModuleName(dependency: Dependency, dynamicImport: string): string {
    if (!this.isHarDependency(dynamicImport)) {
      return '';
    }

    const dependencyRootPath = dependency.getDependencyRootPath();
    const moduleJsonPath = path.resolve(dependencyRootPath, BuildDirConst.SRC, BuildDirConst.MAIN, CommonConst.MODULE_JSON5);
    const moduleOptObj: ModuleOptObj = getJson5Obj(moduleJsonPath);
    return dependency.isLocal() ? moduleOptObj?.module.name ?? '' : DependencyManager.getModuleNameFromOhPkgJson(dependencyRootPath);
  }

  /**
   * 检查dynamicImportLibsInfo中是否已存在依赖信息
   * 处理存在同名但非同版本依赖重复写入dynamicImportLibsInfo的场景
   * 收集依赖遵循距离优先原则 若已写入对象中则跳过后续版本的写入 即模块级优先于工程级依赖调用
   * @param dependencyName
   * @private
   */
  private existInDynamicImportLibsInfo(dependencyName: string): boolean {
    return Object.prototype.hasOwnProperty.call(this.dynamicImportLibInfo, dependencyName);
  }

  /**
   * 判断dynamic import是否为har dependency
   * @param dynamicImport
   * @private
   */
  private isHarDependency(dynamicImport: string): boolean {
    const harDependenciesList: string[] = [];
    this.service.getHarDependencies().forEach((harDependency) => {
      harDependenciesList.push(harDependency.getDependencyName());
    });
    return harDependenciesList.includes(dynamicImport);
  }

  /**
   * 判断dynamic import是否为hsp dependency
   * @param dynamicImport
   * @private
   */
  private isHspDependency(dynamicImport: string): boolean {
    const hspDependenciesList: string[] = [];
    this.service.getHspDependencies().forEach((hspDependency) => {
      hspDependenciesList.push(hspDependency.getDependencyName());
    });
    return hspDependenciesList.includes(dynamicImport);
  }

  /**
   * 将模块routerMap配置信息传递给compileEntry和dynamicImportLibInfo
   * @private
   */
  private processRouterMap(): void {
    const intermediatesToLoaderRouterMap = this.pathInfo.getIntermediatesRouterMap(BuildArtifactConst.LOADER_ROUTER_MAP_FILE_NAME);
    if (!fse.existsSync(intermediatesToLoaderRouterMap)) {
      return;
    }

    const intermediatesTempRouterMapOpt: RouterMapOptions.RouterMapOpt = getJson5Obj(intermediatesToLoaderRouterMap);
    if (!intermediatesTempRouterMapOpt.routerMap?.length) {
      return;
    }

    // 写入compileEntry
    intermediatesTempRouterMapOpt.routerMap.forEach((routerMapObj) => {
      this.compileEntry.push(routerMapObj.pageSourceFile);
    });

    // 写入提供给loader的routerMap中间临时对象仅包含{name,pageSourceFile,buildFunction}
    Object.assign(this.intermediatesRouterMapObjs, intermediatesTempRouterMapOpt.routerMap);
  }

  /**
   * 背景：生成一个版本号更新表给es2abc使用
   * 对比语境信息表和字节码har中的元数据的版本号，如果不一致在记录，如果一直则置为空
   * 记录的是语境信息表中的数据
   * @private
   */
  private processUpdateVersionInfo(): void {
    const isHapOrHsp  =
      this.targetService.getModuleService().getModuleModel().isHapModule() || this.targetService.getModuleService().getModuleModel().isHspModule();
    const isOhosTest = this.targetName === CommonConst.OHOS_TEST;
    const isLocalTest = InjectUtil.isLocalTest();
    const isTestOrPreview =  this.isPreview || isOhosTest || isLocalTest;
    const isHar = this.targetService.getModuleService().getModuleModel().isHarModule();

    // 如果是har的同时是test或者preview 则不return,如果是普通har，则return
    if (!isHapOrHsp && !(isHar && isTestOrPreview)) {
      return;
    }

    const dependencies = this.isByteCodeHarOptimize ?
      this.service.getAllByteCodeHarDependencies() :
      this.targetService.getModuleService().getHarDependencies().filter((d) => d.isByteCodeHarDependency());

    dependencies.forEach((d) => {
      const packageJsonObj = d.getPackageJsonObj() as any;
      // 先赋空值
      this.updateVersionInfo[d.getPackageName()] ||= {};
      const dependencyPkgVersion = packageJsonObj?.metadata?.dependencyPkgVersion;
      // 如果存在dependencyPkgVersion则对比记录版本号不同的依赖，不存在则记录所有
      if (!dependencyPkgVersion) {
        Object.entries({ ...packageJsonObj?.dependencies, ...packageJsonObj?.dynamicDependencies }).forEach(([key]) => {
          const pkgContextInfoVersion = this.pkgContextInfos[key]?.version;
          if (pkgContextInfoVersion && pkgContextInfoVersion.trim() !== '') {
            this.updateVersionInfo[d.getPackageName()][key] = pkgContextInfoVersion;
          }
        });
        return;
      }
      // 遍历 dependencyPkgVersion
      Object.entries(dependencyPkgVersion)
        .filter(([key, value]) => {
          const pkgContextInfoVersion = this.pkgContextInfos[key]?.version;
          return pkgContextInfoVersion !== undefined && pkgContextInfoVersion.trim() !== '' && pkgContextInfoVersion !== value;
        })
        .forEach(([key]) => {
          this.updateVersionInfo[d.getPackageName()][key] = this.pkgContextInfos[key]?.version;
        });
    });
  }

  /**
   * 将字节码har依赖的本地或远程源码har的worker/runtimeOnly/routerMap相关信息写入compileEntry
   * @private
   */
  private processBundledDependencies(): void {
    const dep2ConfigMap = HarTargetUtil.getDep2ConfigMap(this.targetService);
    if (!this.targetService.isByteCodeHar() || !this.isBundledDependencies || !dep2ConfigMap) {
      return;
    }

    // worker
    this.pushConfigToCompileEntry(dep2ConfigMap.dep2Workers);

    // runtimeOnly
    this.pushDepRuntimeOnlyToCompileEntry(dep2ConfigMap?.dep2RuntimeOnlyObj);

    // routerMap
    this.pushConfigToCompileEntry(dep2ConfigMap.dep2RouterMapObjPageSourceFiles);
  }

  private addHarDepInsightSrcEntry(): void {
    // 非bundle的只需要收集自身的入口文件
    if (this.moduleModel.isHarModule() && !this.isBundledDependencies) {
      return;
    }

    const depHar = this.service.getHarDependencies();

    // 把依赖链上的源码har配置的入口文件都收集到compileEntry里
    depHar.forEach(dep => {
      const insightIntentJsonPath = dep.getInsightIntentPath();
      const mainPath = dep.getDependencySrcMainPath();

      // 非源码har或者不存在意图框架配置文件则跳过
      if (dep.isByteCodeHarDependency() || !fse.existsSync(insightIntentJsonPath)) {
        return;
      }

      const insightIntentDataJson = getJson5Obj(insightIntentJsonPath);
      // 依赖链上只收集新的意图框架配置入口，对于老的入口则不做处理
      for (const intent of [...(insightIntentDataJson.insightIntentsSrcEntry ?? [])] ) {
        if (intent.srcEntry) {
          const fullPath = path.resolve(mainPath, intent.srcEntry);
          if (fse.existsSync(fullPath)) {
            this.compileEntry.push(fullPath);
          }
        }
      }

    });
  };

  /**
   * 收集直接、间接依赖源码har的module.json的abilities/srcEntry以及extensionAbilities/srcEntry对应的文件写入到hap、hsp的loader.json中的compileEntry中
   * @private
   */
  private collectDepAbilitySrcEntryArr(): void {
    const depAbilitySrcEntryArr: string[] = [];
    this.service.getHarDependencies().forEach((dependency) => {
      if (dependency.isByteCodeHarDependency()) {
        // 字节码har已合并至abc中所以无需处理
        return;
      }

      const dependencyModuleJsonObj = dependency.getModuleJsonObj();
      if (!dependencyModuleJsonObj) {
        return;
      }

      for (const abilityTypeName of [AbilityConst.UI_ABILITY, AbilityConst.EXTENSION_ABILITY]) {
        const depModuleAbilities = dependencyModuleJsonObj?.module?.[abilityTypeName] as ModuleJson.AbilityObj[] | undefined;
        if (!depModuleAbilities?.length) {
          continue;
        }

        depModuleAbilities.forEach((abilityObj: AbilityObj) => {
          if (!abilityObj.srcEntry) {
            return;
          }

          const absoluteSrcEntryPath = this.targetService.getAbsoluteSrcEntryPath(abilityObj.srcEntry, dependency.getDependencyRootPath());
          if (!fse.existsSync(absoluteSrcEntryPath)) {
            this._log.debug(
              'The srcEntry path for obtaining the ability of the module on which the module depends is incorrect or the corresponding file does not exist.',
            );
            return;
          }

          depAbilitySrcEntryArr.push(absoluteSrcEntryPath);
        });
      }
    });
    this.compileEntry.push(...depAbilitySrcEntryArr);
  }

  /**
   * 将模块本地或远程依赖har模块对应的runtimeOnly的sources和packages的入口文件写入compileEntry
   * @param dep2RuntimeOnlyObj
   * @private
   */
  private pushDepRuntimeOnlyToCompileEntry(dep2RuntimeOnlyObj: Dep2RuntimeOnlyObj | undefined): void {
    if (!dep2RuntimeOnlyObj) {
      return;
    }

    // runtimeOnly-sources
    this.pushConfigToCompileEntry(dep2RuntimeOnlyObj.dep2RuntimeOnlySources);

    // runtimeOnly-packages
    (dep2RuntimeOnlyObj.dep2RuntimeOnlyPackages as Map<Dependency, string[]>).forEach((packages) => {
      packages.forEach((dynamicImportPkg) => {
        const dynamicImportDependency = this.service.getHarDependencies().find((harDep) => {
          return harDep.getDependencyName() === dynamicImportPkg;
        });
        if (!dynamicImportDependency) {
          return;
        }

        const ohPkgJsonObj: OhPackageJsonOpt = Json5Reader.getJson5Obj(dynamicImportDependency.getPackageFilePath());
        const mainFilePath = ohPkgJsonObj.main ? dynamicImportDependency.getDependencyMainFilePath() : dynamicImportDependency.getDependencyTypesFilePath();
        if (fse.existsSync(mainFilePath)) {
          this.compileEntry.push(mainFilePath);
        }
      });
    });
  }

  /**
   * 将模块本地或远程依赖har模块的worker/runtimeOnly-sources/routerMapObj-pageSourceFile的入口文件写入compileEntry
   * runtimeOnly-packages单独处理
   * @param configMap
   * @private
   */
  private pushConfigToCompileEntry(configMap: Map<Dependency, string[]> | undefined): void {
    if (!configMap?.size) {
      return;
    }

    configMap.forEach((configArr, dependency) => {
      configArr.forEach((config) => {
        const absoluteConfigPath = path.resolve(dependency.getDependencyRootPath(), config);
        if (fse.existsSync(absoluteConfigPath)) {
          this.compileEntry.push(absoluteConfigPath);
        }
      });
    });
  }
}

/**
 * 写入dynamicImportLibInfo的dynamicImport对象
 */
export interface DynamicImportObj {
  hostModulesInfo: HostModulesInfoObj[]; // 依赖信息
  moduleName: string; // 依赖的名称:本地依赖则为依赖的module.json5中的name;远程依赖则为依赖的oh-package.json5中的name;.so为oh-package.json5中的name
  entryFilePath: string; // 依赖的入口文件绝对路径
  isLocalDependency: boolean; // 是否为本地依赖
  pkgPath: string; // 依赖最上层绝对路径
}

/**
 * 三方包信息对象
 */
export interface HostModulesInfoObj {
  hostDependencyName: string; // 依赖package.json中的name (同dynamicImport)
  hostModuleName: string; // 依赖该dependency的模块名
}
